/*
 * Copyright (C) 2010 Seapeak.Xu
 *
 * fostmq may be copied only under the terms of the GNU General
 * Public License V3, which may be found in the fostmq source kit.
 *
 * Created on: 2010-7-30
 * Author: Seapeak.Xu
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>

#include "fost_mgnb.h"
#include "fost_mem.h"
#include "fost_typedef.h"
#include "fost_logger.h"
#include "fost_io.h"

int is_dir(const char *path)
{
	struct stat buf;
	int result = 0;
	if (-1 == stat(path, &buf))
	{
		result = 0 == errno ? EACCES : errno;
		return result;
	}

	return S_ISDIR(buf.st_mode) ? 0 : -1;
}

int mkdir_cascading(const char *path, mode_t mode)
{
	int result = 0;
	if (NULL == path)
	{
		result = 0 == errno ? EINVAL : errno;
		log_warn("File:%s,Line:%d,Function:%s.the argument is null.Error:%d,Info:%s.",
			__FILE__,__LINE__, __FUNCTION__,result,strerror(result));
		return result;
	}
	int len, ptrlen = 0;
	char *postion;
	char *path_temp = (char *) path;
	char *subfolder;

	char *cwd = fost_callocs(PATH_LEN);
	if(NULL == cwd)
	{
		result = errno;
		log_error("File:%s,Line:%d,Function:%s.malloc memory to current path is error.Errno:%d,Info:%s.",
				__FILE__,__LINE__,__FUNCTION__,result,strerror(result));
		return result;
	}
	do
	{
		getcwd(cwd,PATH_LEN);

		if (*path_temp == '/')
		{
			if (-1 == chdir("/"))
			{
				result = errno;
				log_error("File:%s,Line:%d,Function:%s.Info:Change the current path to root directory is error.Errno:%d,Info:%s",
						__FILE__, __LINE__, __FUNCTION__, result,strerror(result));
				break;
			}
			ptrlen++;
		}

		while (ptrlen != strlen(path_temp))
		{
			postion = strchr(path_temp + ptrlen, '/');
			len = 0 == postion ? strlen(path_temp) - ptrlen : postion - path_temp - ptrlen;
			
			do
			{
				subfolder = fost_callocs(len);
				if (NULL == subfolder)
				{
					result = errno;
					log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__,
							__LINE__, __FUNCTION__, result,strerror(result));
					break;
				}
				memcpy(subfolder, path_temp + ptrlen, len);
				*(subfolder + len) = '\0';

				if (0 == (result = is_dir(subfolder)))
				{
					if (0 != chdir(subfolder))
					{
						result = 0 == errno ? EACCES : errno;
						log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__,
								__LINE__, __FUNCTION__, result,strerror(result));
					}
					break;
				}
		
				if (-1 == (result == mkdir(subfolder, mode)))
				{
					result = errno;
					log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__,
							__LINE__, __FUNCTION__, result,strerror(result));
					break;
				}
				if (-1 == (result = chdir(subfolder)))
				{
					result = errno;
					log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__,
							__LINE__, __FUNCTION__, result,strerror(result));
					break;
				}
			} while (false);

			FOST_FREE(subfolder);
			ptrlen += 0 == postion ? len : len + 1;
		}

		if(NULL != cwd) 
		{
			chdir(cwd);
		}
	}while(false);
	if(NULL != cwd) 
	{	
		FOST_FREE(cwd);	
	}
	return result;
}

int fill_file(const char *filepath,const char *format,...)
{
	FILE *file = fopen(filepath,"w+");
	if(NULL == file)
	{
		log_error("File:%s,Line:%d,Function:%s.open the file for stream.error:%d,info:%s.",
				__FILE__,__LINE__,__FUNCTION__,errno,strerror(errno));
		return -1;
	}
	va_list ap;
	va_start(ap,format);
	if(0 > vfprintf(file,format,ap))
	{
		log_error("File:%s,Line:%d,Function:%s.flush the buffer to file is error.errno:%d,info:%s.",
				__FILE__,__LINE__,__FUNCTION__,errno,strerror(errno));
		return -1;
	}
	va_end(ap);
	fflush(file);
	fclose(file);
	return 0;
}

